package cn.happiness.frog.skill.service;

import cn.happiness.frog.skill.service.dto.Song;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.*;

@Service
@Slf4j
public class SongService {

	public static final String SONG_DIR = Optional.ofNullable(System.getenv("SONG_DIR"))
			.orElse("music/songs");

	public static final String SONG_URL = Optional.ofNullable(System.getenv("SONG_URL"))
			.orElse("https://nginx.happiness-frog.cn/mp3/");

	private static final List<Song> songs = Song.fromPath(SONG_DIR);

	private static final List<String> songNames = songs.stream().map(Song::getName).distinct().toList();
	private static final List<String> types = Arrays.asList("跟弹", "伴奏", "示范");
	private static final List<String> speeds = Arrays.asList("慢速", "中速", "快速");


	/**
	 * 小星星,04A 小星星慢速跟弹.mp3
	 * 小星星,04B 小星星（伴奏）-慢速66.mp3
	 * 小星星,04C 小星星（伴奏）-中速76.mp3
	 * 小星星,04D小星星（伴奏）-快速92.mp3
	 * 小星星,04E 小星星（示范）-快速.mp3
	 *
	 * @param text
	 * @return songURL
	 */
	public String findSongURL(final String text) {
		Song song = findSong(text);
		log.info("find song: {}", song);
		return Optional.ofNullable(song)
				.map(s -> UriComponentsBuilder.fromHttpUrl(SONG_URL).path(s.getKey()).encode().build().toUriString())
				.orElse(null);
	}

	private Song findSong(String text) {
		String songName = match(songNames, text);
		if (songName == null) {
			return null;
		}
		String type = match(types, text);
		String speed = match(speeds, text);

		List<Song> songsByName = songs.stream().filter(song -> StringUtils.contains(song.getKey(), songName)).toList();
		List<Song> songsByType = songsByName.stream().filter(song -> StringUtils.contains(song.getKey(), type)).toList();
		List<Song> songsBySpeed = songsByName.stream().filter(song -> StringUtils.contains(song.getKey(), speed)).toList();

		if (!songsBySpeed.isEmpty()) {
			return songsBySpeed.get(0);
		}
		if (!songsByType.isEmpty()) {
			return songsByType.get(0);
		}
		if (!songsByName.isEmpty()) {
			return songsByName.get(0);
		}
		return null;
	}

	private String match(List<String> texts, String search) {
		List<CharCountText> charCountTexts = texts
				.stream()
				.map(text -> {
					Integer count = matchCharCount(text, search);
					return new CharCountText(text, search, count);
				})
				.filter(text -> text.getCount() > 0)
				.sorted(Comparator.comparing(CharCountText::getCount).reversed())
				.toList();
		if (charCountTexts.isEmpty()) {
			return null;
		}
		return charCountTexts.get(0).getText();
	}

	private Integer matchCharCount(String text, String search) {

		// 将 text 和 search 转换为小写，以便进行大小写不敏感的匹配
		text = text.toLowerCase();
		search = search.toLowerCase();

		// 判断 text 是否包含中文字符（通过正则表达式检测）
		boolean isChinese = search.matches(".*[\\u4e00-\\u9fa5].*");

		if (isChinese) {
			return matchChineseCount(text, search);
		} else {
			return matchWordsCount(text, search);
		}
	}

	private Integer matchWordsCount(String text, String search) {
		int count = 0;
		String[] words = search.split("\\s+"); // 按空格分割文本为单词

		// 遍历每个单词，判断它是否在 search 中
		for (String word : words) {
			if (text.contains(word)) {
				count++;
			}
		}
		return count;
	}

	private Integer matchChineseCount(String text, String search) {
		int count = 0;
		// 如果 search 包含中文字符，按字符匹配
		Set<Character> textSet = new HashSet<>();
		// 将 search 字符串中的字符存入 Set 中
		for (int i = 0; i < text.length(); i++) {
			textSet.add(text.charAt(i));
		}

		// 遍历 text 字符串中的每个字符，判断是否在 textSet 中
		for (char c :search.toCharArray()){
			if (textSet.contains(c)) {
				count++;
			}
		}
		return count;
	}

	@Data
	@AllArgsConstructor
	public static class CharCountText {
		private String text;
		private String search;
		private Integer count;
	}

}
